<?php
class NewShopService {

    /**
     * @var NewShopService
     */
    private static $instance;

    /**
     * Get the instance of NewShopService
     * @return NewShopService
     */
    public static function get() {
        if (!self::$instance) {
            self::$instance = new NewShopService();
        }
        return self::$instance;
    }

    /**
     * Construction.
     */
    public function __construct() {

    }

    /**
     * 数据
     * @param $userId
     * @param $reqTime
     * @return array
     * @throws SzException
     */
    public function shopInfo($userId,$reqTime) {
        /**
         * @var ModuleProfileVo $profile
         * @var ModuleProfileInfoVo $refreshTimeInfo
         * @var NewShopVo $userNewShop
         */
        $profile = SzPersister::get()->getVo($userId, ModuleProfileConst::ORM_NAME_PROFILE);
        $userLevel = $profile->getLevel();

        $shopLevelSetting = SzConfig::get()->loadAppConfig(GameConst::CONFIG_SHOP_LEVEL, $userLevel, true);
        if (!$shopLevelSetting) {
            throw new SzException(29024,$userLevel); // 商店等级表没数据
        }

        $shopItemNum = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'shopItemNum', true);

        $userNewShopList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_SHOP);
        $profileInfoList = SzPersister::get()->getVoList($userId, ModuleProfileConst::ORM_NAME_PROFILE_INFO);
        $freeTime = $this->getFreeTime($userId,$reqTime,$profileInfoList);
        if (!$userNewShopList->getList()) {
            // 数据未生成
            $reward = $this->getItemInfo($shopItemNum['value'],$shopLevelSetting);

            // 刷新
            $refreshTimeInfo = $profileInfoList->getElement(GameConst::USER_INFO_TYPE_REFRESH_TIME,false);
            if (!$refreshTimeInfo) {
                $refreshTimeInfo = new ModuleProfileInfoVo(
                    $userId,
                    GameConst::USER_INFO_TYPE_REFRESH_TIME,
                    0,
                    $reqTime,
                    true
                );
                $profileInfoList->addElement($refreshTimeInfo);
                $profileInfoList->setElement(GameConst::USER_INFO_TYPE_REFRESH_TIME, $refreshTimeInfo);
            }
            foreach ($reward as $position=>$val) {
                $userNewShop = new NewShopVo($userId,$position,json_encode($val['buy'],true),json_encode($val['cost'],true), 0,true);
                $userNewShopList->addElement($userNewShop);
                $userNewShopList->setElement($position,$userNewShop);
            }
            SzPersister::get()->setVoList($userNewShopList);
            SzPersister::get()->setVoList($profileInfoList);
            $refreshTime = $reqTime;
        } else {
            $shopRefreshTime = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'shopRefreshTime', true);
            $reward = $this->getItemInfo($shopItemNum['value'],$shopLevelSetting);
            // 刷新
            $refreshTimeInfo = $profileInfoList->getElement(GameConst::USER_INFO_TYPE_REFRESH_TIME);
            if ( ($refreshTimeInfo->getTime() + $shopRefreshTime['value']) <= $reqTime) {
                foreach ($reward as $position=>$val) {
                    $userNewShop = $userNewShopList->getElement($position);
                    $userNewShop->setCostItemList($val['cost']);
                    $userNewShop->setBuyItemList($val['buy']);
                    $userNewShop->setIsBuy(0);
                    $userNewShopList->updateElement($position,$userNewShop);
                }
                $refreshTimeInfo->setTime($reqTime);
                $refreshTimeInfo->setInfo(0);
                $profileInfoList->updateElement(GameConst::USER_INFO_TYPE_REFRESH_TIME,$refreshTimeInfo);
                SzPersister::get()->setVoList($profileInfoList);
                SzPersister::get()->setVoList($userNewShopList);
                $refreshTime = $reqTime;
            } else {
                $refreshTime = $refreshTimeInfo->getTime();
            }
        }
        return array(
            'refreshTime' => $refreshTime,
            'freeTime' => $freeTime,
            'shopList' => $userNewShopList->toArray()
        );
    }

    /**
     * 刷新商店
     * @param $userId
     * @param $reqTime
     * @return array|void
     * @throws SzException
     */
    public function refreshShop($userId,$reqTime) {
        /**
         * @var ModuleProfileVo $profile
         * @var ModuleProfileInfoVo $refreshTimeInfo
         * @var NewShopVo $userNewShop
         * @var ModuleProfileInfoVo $shopFreeTimeInfo
         */
        $profile = SzPersister::get()->getVo($userId, ModuleProfileConst::ORM_NAME_PROFILE);
        $userLevel = $profile->getLevel();

        $shopLevelSetting = SzConfig::get()->loadAppConfig(GameConst::CONFIG_SHOP_LEVEL, $userLevel, true);
        if (!$shopLevelSetting) {
            throw new SzException(29024,$userLevel); // 商店等级表没数据
        }

        $shopItemNum = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'shopItemNum', true);

        $userNewShopList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_SHOP);
        if (!$userNewShopList->getList()) {
            throw new SzException(29026,$userId);
        }
        $profileInfoList = SzPersister::get()->getVoList($userId, ModuleProfileConst::ORM_NAME_PROFILE_INFO);
        $freeTime = $this->getFreeTime($userId,$reqTime,$profileInfoList);
        $shopFreeTime = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'shopFreeTime', true);
        $surplus = $freeTime - $shopFreeTime['value'];
        if ($surplus >= 0) {
            $costItem =  SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'costItem', true);
            if (!$costItem) {
                throw new SzException(29027,$freeTime);
            }

            $costItem = json_decode($costItem['value'],true);

            $length = count($costItem);

            if ($surplus >= $length) {
                $itemList = $costItem[$length - 1];
            } else {
                $itemList = $costItem[$surplus];
            }

            $output = '';
            foreach ($itemList as $entityId=>$count) {
                GameService::get()->handleEntity($userId, $entityId, $count, true);
                $output .= $entityId.':'.$count.'|';
            }
            CommonFunctionService::get()->reportResourceUseDetails(GameConst::FUNC_RANDOM_SHOP,$userId,0,$output,'refreshShop');//消耗资源上报

        }
        $reward = $this->getItemInfo($shopItemNum['value'],$shopLevelSetting);
        foreach ($reward as $position=>$val) {
            $userNewShop = $userNewShopList->getElement($position);
            $userNewShop->setCostItemList($val['cost']);
            $userNewShop->setBuyItemList($val['buy']);
            $userNewShop->setIsBuy(0);
            $userNewShopList->updateElement($position,$userNewShop);
        }

        $freeTime += 1;
        $refreshTimeInfo = $profileInfoList->getElement(GameConst::USER_INFO_TYPE_REFRESH_TIME);
        $shopFreeTimeInfo = $profileInfoList->getElement(GameConst::USER_INFO_TYPE_FREE_TIME);
        $shopFreeTimeInfo->setTime($reqTime);
        $shopFreeTimeInfo->setInfo(intval($freeTime));
        $refreshTimeInfo->setTime($reqTime);
        $refreshTimeInfo->setInfo(0);
        $profileInfoList->updateElement(GameConst::USER_INFO_TYPE_REFRESH_TIME,$refreshTimeInfo);
        $profileInfoList->updateElement(GameConst::USER_INFO_TYPE_FREE_TIME,$shopFreeTimeInfo);
        SzPersister::get()->setVoList($profileInfoList);
        SzPersister::get()->setVoList($userNewShopList);
        // 数据采集:行为
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:shop|action:refresh|',
                'value' => 1
            )
        ));
        return array(
            'refreshTime' => $reqTime,
            'freeTime' => $freeTime,
            'shopList' => $userNewShopList->toArray()
        );
    }

    /**
     * @param $userId
     * @return bool|void
     * @throws SzException
     */
    public function buyShop($userId,$position) {
        /**
         * @var ModuleProfileVo $profile

         * @var NewShopVo $userNewShop
         */
        $userNewShopList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_SHOP);
        $userNewShop = $userNewShopList->getElement($position);
        if ($userNewShop->getIsBuy()) {
            throw new SzException(29028);
        }

        $useGold = 0;
        $inputTid = '';
        $outputTid = '';
        foreach ($userNewShop->getRawCostItemList() as $entityId=>$count) {
            GameService::get()->handleEntity($userId, $entityId, $count, true);
            if ($entityId == GameConst::ENTITY_ACTION_CONSUME_MONEY) {
                $useGold = $count;
            }
            $inputTid .= $entityId.':'.$count.'|';
        }
        CommonFunctionService::get()->reportResourceUseDetails(GameConst::FUNC_RANDOM_SHOP,$userId,0,$inputTid,'buyShop');//消耗资源上报

        $itemId = 0;
        foreach ($userNewShop->getRawBuyItemList() as $entityId=>$count) {
            GameService::get()->handleEntity($userId, $entityId, $count, true);
            $itemId = $entityId;
            $outputTid .= $entityId.':'.$count.'|';
        }
        CommonFunctionService::get()->reportResourceUseDetails(GameConst::FUNC_RANDOM_SHOP,$userId,1,$outputTid,'buyShop');//获得资源上报

        $userNewShop->setIsBuy(1);
        $userNewShopList->updateElement($position,$userNewShop);
        SzPersister::get()->setVoList($userNewShopList);

        NewTaskService::get()->updateProgress($userId,GameConst::TASK_SHOP_BUY,1);

        // 数据采集:行为
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:item|action:buy|',
                'item' => $itemId,
                'value' => 1
            )
        ));

        if ($useGold) {
            // 数据采集:钻石
            StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USE_GOLD, array(
                'clientData' => array(
                    'item' => 'item_buy&'.$itemId,
                    'value' => $useGold
                )
            ));
        }

        // 数据采集:获得
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_RESOURCE_OUTPUT, array(
            'clientData' => array(
                'tid' => $outputTid,
                'item' => 'item_buy',
            )
        ));

        // 数据采集:消耗
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_RESOURCE_INPUT, array(
            'clientData' => array(
                'tid' => $inputTid,
                'item' => 'item_buy&'.$itemId,
            )
        ));

        TrainingService::get()->updateProgress($userId,GameConst::TRAINING_TASK_SHOP_BUY,1);

        //社团竞赛任务进度添加
        UnionCompetitionService::get()->addCompetitionTaskProcess($userId,GameConst::UNION_COMPETITION_TASK_10, GameService::get()->getReqTime(),1);

        return true;
    }

    /**
     * 随机道具
     * @param $shopItemNum
     * @param $shopLevelSetting
     * @return array
     */
    private function getItemInfo($shopItemNum,$shopLevelSetting) {
        $shopItemSettings = SzConfig::get()->loadAppConfig(GameConst::CONFIG_SHOP_ITEM, null, true);
        $list = array();

        for ($i=1; $i<=$shopItemNum; $i++) {
            $key = array_rand($shopLevelSetting['shopItemId']);
            $shopItemId = $shopLevelSetting['shopItemId'][$key];
            if (!isset($shopItemSettings[$shopItemId])) {
                throw new SzException(29025, $shopItemId); // ft_shop_item id不存在
            }
            $shopItemSetting = $shopItemSettings[$shopItemId];
            list($min,$max) = $shopLevelSetting['itemNum'];
            $buyNum = mt_rand($min,$max);
            list($min,$max) = $shopItemSetting['price'];
            $price = mt_rand($min,$max);
            $list[$i] = array(
                'cost' => array(
                    $shopItemSetting['costItem'] => ($buyNum * $price)
                ),
                'buy' => array(
                    $shopItemSetting['getItem'] => $buyNum
                ),
            );
        }
        return $list;
    }

    /**
     * 获取免费次数
     * @param $userId
     * @param $reqTime
     * @return int
     * @throws SzException
     */
    private function getFreeTime($userId,$reqTime,$profileInfoList) {
        /**
         * @var ModuleProfileInfoVo $shopFreeTimeInfo
         */
        $shopFreeTimeInfo = $profileInfoList->getElement(GameConst::USER_INFO_TYPE_FREE_TIME, false);
        $num = 0;
        if (!$shopFreeTimeInfo) {
            $shopFreeTimeInfo = new ModuleProfileInfoVo(
                $userId,
                GameConst::USER_INFO_TYPE_FREE_TIME,
                0,
                $reqTime,
                true
            );
            $profileInfoList->addElement($shopFreeTimeInfo);
            $profileInfoList->setElement(GameConst::USER_INFO_TYPE_FREE_TIME, $shopFreeTimeInfo);
            SzPersister::get()->setVoList($profileInfoList);
        } else {
            // 日期不一致
            if(SzTime::getDate($shopFreeTimeInfo->getTime()) != SzTime::getDate($reqTime)) {
                $shopFreeTimeInfo->setTime($reqTime);
                $shopFreeTimeInfo->setInfo(0);
                $profileInfoList->updateElement(GameConst::USER_INFO_TYPE_FREE_TIME, $shopFreeTimeInfo);
                SzPersister::get()->setVoList($profileInfoList);
                SzPersister::get()->setVoList($profileInfoList);
            }
            $num = $shopFreeTimeInfo->getInfo();
        }
        return $num;
    }
}